package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.crypto.SecureUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.feign.DbServiceFeign;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.UserInfoVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserManager {

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private DbServiceFeign dbServiceFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //保存用户,返回主键
    public Long save(User user) {
        //密码加密
        String md5Password = SecureUtil.md5(user.getPassword());
        user.setPassword(md5Password);

        return dbServiceFeign.save(user);
    }

    //根据手机号查询用户
    public User findByPhone(String phone) {
        return dbServiceFeign.findByPhone(phone);
    }

    //完善个人基本信息
    public void saveUserBaseInfo(UserInfo userInfo) {
        dbServiceFeign.save(userInfo);
    }

    //完善个人头像信息
    public void saveUserHeadInfo(Long id, MultipartFile headPhoto) throws IOException {
        //1. 人脸识别,如果识别失败,返回异常
        /*boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        System.out.println("人脸识别的结果:" + detect);
        if (!detect) {
            throw new RuntimeException("人脸审核失败");
        }*/

        //2. 阿里云文件上传,获取到访问地址
        String filePath = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        System.out.println("文件上传之后的路径:" + filePath);

        //3. 更新数据表user_info
        UserInfo userInfo = new UserInfo();//update set
        userInfo.setId(id);// where id = ?
        userInfo.setAvatar(filePath);//set avatar = filePath
        userInfo.setCoverPic(filePath);//coverPic = filePath
        dbServiceFeign.update(userInfo);
    }

    //根据id查询
    public UserInfoVo findById(Long userID) {
        //1. 查询
        UserInfo userInfo = dbServiceFeign.findById(userID);
        System.out.println(userInfo);

        //2. 结果封装
        UserInfoVo userInfoVo = new UserInfoVo();
        //2-1 复制属性,两个对象中的属性名称和类型必须完全一致
        BeanUtil.copyProperties(userInfo, userInfoVo);
        //2-2 单独复制age
        userInfoVo.setAge(userInfo.getAge() + "");

        //3. 返回结果
        return userInfoVo;
    }

    //更新个人信息
    public void updateUserBaseInfo(UserInfo userInfo) {
        dbServiceFeign.update(userInfo);
    }

    //根据id查User
    public User findUserById(Long userId) {
        return   dbServiceFeign.findUserById(userId);
    }
    //校验验证码
    public Map<String, Boolean> checkCode(String code) {
        Long id = UserHolder.get().getId();
        User user = dbServiceFeign.findUserById(id);
        String phone = user.getPhone();
        //从redis中获取验证码
        String s = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        if(!StringUtils.equals(code,s)){
            throw new RuntimeException("验证码错误");
        }
        Map<String, Boolean> map = new HashMap<>();
        map.put("verification", true);
        return map;
    }

    //修改电话号码
    public void updatePhone(String phone) {
        Long id = UserHolder.get().getId();
        User user = findByPhone(phone);
        if (user != null) {
            throw new RuntimeException("电话号码重复");
        }

        dbServiceFeign.updatePhone(phone,id);
    }

    //登录发送验证码
    public String sendSmsCode(String phone) {
        String code = String.format("%06d", (int) (Math.random() * 999999));
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone, code, Duration.ofMinutes(1));
        return code;
    }

    //登录生成token
    public Map<String,Object> login(String phone, String code) {
        //1. 校验验证码
        Map<String, Boolean> map = checkverificationCode(phone,code);
        if (!map.get("success")) {
            return null;
        }
        //2.查询用户id和phone
        User user = findByPhone(phone);
        if (user == null){
            return null;
        }
        //3. 生成 token
        Map claims = new HashMap();
        claims.put("id", user.getId());
        claims.put("phone", phone);
        claims.put("code", code);
        String token =JwtUtil.createToken(claims);

        //4. 封装返回信息
        Map<String,Object> map1 = new HashMap();
        map1.put("isNew", false);
        map1.put("token", token);

        //5.发送MQ消息
        Log log = new Log();
        log.setUserId(user.getId());
        log.setLogTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        log.setPlace("用户登录");
        log.setEquipment("web");
        log.setType("0101");
        log.setCreated(new Date());
        log.setUpdated(new Date());
        rabbitTemplate.convertAndSend("tanhua.topic", "log", log);
        return map1;
    }

    //登录校验验证码
    public Map<String, Boolean> checkverificationCode(String phone, String code) {
        //从redis中获取验证码
        String s = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        if(!StringUtils.equals(code,s)){
            throw new RuntimeException("验证码错误");
        }
        Map<String, Boolean> map = new HashMap<>();
        map.put("success", true);
        return map;
    }
}